package cn.kmust.booth.portal.service.impl;

import cn.kmust.booth.portal.mapper.AdminMapper;
import cn.kmust.booth.portal.model.Admin;
import cn.kmust.booth.portal.security.UserInfo;
import cn.kmust.booth.portal.service.IAdminService;
import cn.kmust.booth.portal.service.ex.*;
import cn.kmust.booth.portal.vo.R;
import com.aliyuncs.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author kmust.cn
 * @since 2020-08-06
 */
@Service
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    public UserDetails login(String phone) {

        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        Admin admin = adminMapper.selectOne(queryWrapper);

        if(admin ==null){
            return null;
        }
        UserInfo userInfo = new UserInfo(
                admin.getPhone(),
                admin.getPassword(),
                true,
                true,
                true,
                true,
                AuthorityUtils.createAuthorityList()
        );
        userInfo.setJobNumber(admin.getJobNumber());
        userInfo.setUsername(admin.getUsername());
        userInfo.setAvatarUrl(admin.getAvatarUrl());
        userInfo.setFlag(admin.getFlag());
        userInfo.setCity(admin.getCity());

        return userInfo;
    }

    @Override
    public void addAdmin(Admin admin) {
        //工号为空异常 JobNumberJNullException
        if(admin.getJobNumber()==null){
            throw new JobNumberJNullException("添加失败!工号不允许为空,请添加工号!");
        }

        QueryWrapper<Admin> qw = new QueryWrapper<>();
        qw.eq("job_number",admin.getJobNumber());
        Admin resultJobNum = adminMapper.selectOne(qw);
        if(resultJobNum!=null){
            //工号已存在
            throw new JobNumberDuplicateException("添加失败! 该工号已存在!");
        }

        String phone = admin.getPhone();
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        Admin resultPhone = adminMapper.selectOne(queryWrapper);
        // 判断查询结果是否不为null
        if (resultPhone!=null){
            //手机号码已存在异常 PhoneDuplicateException
            throw new PhoneDuplicateException("添加失败!该手机号已经被使用!");
        }

        //将密码进行加密操作
        String rawPassword = admin.getPassword();
        String encodePassword = encode(rawPassword);
        admin.setPassword(encodePassword);

        // 调用AdminMapper对象的insert()方法，根据参数user插入数据，获取返回值
        int rows = adminMapper.insert(admin);
        if(rows!=1){
            //服务器繁忙添加失败 InsertException
            throw new InsertException("添加失败! 服务器繁忙!");
        }
    }

    @Override
    public void updatePassword(String phone, String newPassword, String sms) {
        //首先先通过手机号查找该用户 判断该用户是否存在
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("phone",phone);
        Admin admin = adminMapper.selectOne(queryWrapper);
        if(admin==null){
            throw new PhoneDuplicateException("手机号不存在");
        }
        //判断验证码是否正确
        //重redis得到验证码
        String code = redisTemplate.opsForValue().get(phone);
        if(code==null){
            throw new CodeException("验证码已过期");
        }
        if(!code.equals(sms)){
            throw new CodeException("验证码填写错误");
        }
        //判断新的密码是否与原密码相同
        if(passwordEncoder.matches(newPassword,admin.getPassword())){
            throw new PasswordException("新密码与原密码相同");
        }else{
            //通过以上判断则证明可以修改密码
            Integer rows = adminMapper.updatePwd(encode(newPassword),phone);
            if(rows!=1){
                throw new UpdateException("修改失败,请稍后再试!");
            }
        }
    }

    /**
     * 执行密码加密
     * @param rawPassword 原密码
     * @return 根据原密码执行加密得到的密文
     */
    private String encode(String rawPassword){
        String encodePassword = passwordEncoder.encode(rawPassword);
        encodePassword = "{bcrypt}" + encodePassword;
        return encodePassword;
    }
}
